package com.peking.donations.plugins.oauth2.client;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.peking.donations.plugins.oauth2.client.wechart.WechartOAuth2AccessTokenMessageConverter;
import com.peking.donations.plugins.oauth2.client.wechart.WechartUserInfoTokenService;
import com.peking.donations.plugins.oauth2.client.wechart.WxAuthorizationCodeAccessTokenProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
import org.springframework.security.oauth2.client.token.AccessTokenProviderChain;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;

import java.util.Arrays;
import java.util.List;

/**
 * @author Vigor Yuan
 */
@Configuration
@AutoConfigureAfter
public class UserTokenServiceConfiguration {


    @Value("${spring.profiles.active}")
    String profile;

    @Bean(name = "gitHubOAuth2Resource")
    @ConfigurationProperties(prefix = "oauth2.github")
    OAuth2Resource gitHubOAuth2Resource() {
        return new OAuth2Resource();
    }

    @Bean(name = "wechartOAuth2Resource")
    @ConfigurationProperties(prefix = "oauth2.wechart")
    OAuth2Resource wechartOAuth2Resource() {
        return new OAuth2Resource();
    }

    @Autowired(required = false)
    private OAuth2ClientContext oauth2ClientContext;

    @Bean(name = "gitHubTokenService")
    UserInfoTokenServices gitHubTokenService() {
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(gitHubOAuth2Resource().getUserInfoUri(),
                gitHubOAuth2Resource().getClientId());
        tokenServices.setRestTemplate(gitHubRestTemplate());
        return tokenServices;
    }

    @Bean(name = "gitHubOAuth2RestTemplate")
    public OAuth2RestOperations gitHubRestTemplate() {
        return new OAuth2RestTemplate(gitHubOAuth2Resource(), oauth2ClientContext);
    }

    @Bean(name = "wechartTokenService")
    ResourceServerTokenServices wechartTokenService() {
        WechartUserInfoTokenService tokenServices = new WechartUserInfoTokenService(
                wechartOAuth2Resource().getUserInfoUri(), wechartOAuth2Resource().getClientId());
        tokenServices.setRestTemplate(wechartOAuth2RestTemplate());
        tokenServices.setProfile(profile);
        return tokenServices;
    }

    @Bean(name = "wechartOAuth2RestTemplate")
    public OAuth2RestOperations wechartOAuth2RestTemplate() {
        OAuth2RestTemplate auth2RestTemplate = new OAuth2RestTemplate(wechartOAuth2Resource(), oauth2ClientContext);

        WxAuthorizationCodeAccessTokenProvider provider = new WxAuthorizationCodeAccessTokenProvider();
        provider.setProfile(profile);
        List list = Arrays.asList(new HttpMessageConverter[]{new WechartOAuth2AccessTokenMessageConverter()});
        provider.setMessageConverters(list);

        auth2RestTemplate.setAccessTokenProvider(
                new AccessTokenProviderChain(Arrays.asList(new AccessTokenProvider[] { provider })));

        List list1 = Arrays.asList(new HttpMessageConverter[] { fastJsonHttpMessageConverter() });

        auth2RestTemplate.setMessageConverters(list1);
        return auth2RestTemplate;
    }

    @Bean
    FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        converter.setSupportedMediaTypes(Arrays.asList(
                new MediaType[] { MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8 }));
        return converter;
    }

}
